﻿// SCSO.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <vector>
#include <random>
#include <cmath>
#include <math.h>
#include <fstream>
#include <string>
#include <ctime>
#include "func_state.h"
using namespace std;
double pi = 3.1415;

population initialize(int popSize, int dim, vector<double>ub, vector<double>lb)
{
	population origin_pop;
	for (int i = 0; i < popSize; i++)
	{
		posi temp;
		for (int j = 0; j < dim; j++)
		{
			random_device rd;
			default_random_engine eng(rd());
			uniform_real_distribution<double> distr(lb[j], ub[j]);
			temp.push_back(distr(eng));
		}
		origin_pop.push_back(temp);
		temp.clear();
	}
	return origin_pop;
}

void displayPop(const population pop)
{
	for (int i = 0; i < pop.size(); i++)
	{
		for (int j = 0; j < pop[i].size(); j++)
		{
			cout << pop[i][j] << "   ";
		}
		cout << endl;
	}
}

vector<double>calFitness(int func, const population pop)
{
	vector<double>scores;
	switch (func)
	{
	case 1:
		for (int i = 0; i < pop.size(); i++)
		{
			double result;
			double x1 = pop[i][0];
			double x2 = pop[i][1];
			result = pow(x2 - (5.1 / (4 * pow(pi, 2))) * pow(x1, 2) + (5 / pi) * x1 - 6, 2) + 10 * (1 - 1 / (8 * pi)) * cos(x1) + 10;
			scores.push_back(result);
		}
	case 2:
		for (int i = 0; i < pop.size(); i++)
		{
			double result;
			double x1 = pop[i][0];
			double x2 = pop[i][1];
			result = (1 + pow(x1 + x2 + 1, 2) * (19 - 14 * x1 + 3 * pow(x1, 2) - 14 * x2 + 6 * x1 * x2 + 3 * pow(x2, 2))) * (30 + pow(2 * x1 - 3 * x2, 2) * (18 - 32 * x1 + 12 * pow(x1, 2) + 48 * x2 - 36 * x1 * x2 + 27 * pow(x2, 2)));
			scores.push_back(result);
		}
	default:
		break;
	}

	return scores;
}

posi scso(int popSize, int dim, vector<double>ub, vector<double>lb, int maxIter, int func, vector<double>&bestScores)
{
	double bestScore = 1000;
	bestScores.push_back(bestScore);
	posi bestPosi;
	for (int i = 0; i < dim; i++)
		bestPosi.push_back(0);
	population Popu = initialize(popSize, dim, ub, lb);
	//cout << "初始化的位置：" << endl;
	//displayPop(Popu);
	vector<double>originScores = calFitness(func, Popu);
	//cout << "初始化后的得分：" << endl;
	for (int m = 0; m < originScores.size(); m++)
	{
		if (originScores[m] < bestScore)
		{
			bestScore = originScores[m];
			bestPosi.clear();
			for (int n = 0; n < dim; n++)
			{
				bestPosi.push_back(Popu[m][n]);
			}
		}
	}
	bestScores.push_back(bestScore);

	
	for (int i = 0; i < maxIter; i++)
	{
		//for (int j = 0; j < popSize; j++)
		//{
		//	bool flagUb, flagLb = 0;
		//	for (int k = 0; k < dim; k++)
		//	{
		//		flagUb = Popu[j][k] > ub[k];
		//		flagLb = Popu[j][k] > lb[k];
		//		Popu[j][k] = Popu[j][k] * (!(flagUb + flagLb)) + ub[k] * flagUb + lb[k] * flagLb;
		//	}
		//}

		double sm = 2;
		double rg = sm - (double(sm * (i + 1)) / maxIter);
		for (int j = 0; j < popSize; j++)
		{
			int N = rand() % 1000;
			double r = (N / 1000.0) *rg;//随机产生0到1的小数
			double RR = ((2 * rg) * (rand() % 1000) / 1000.0) - rg;
			for (int k = 0; k < dim; k++)
			{
				int teta = rand() % 360 + 1;
				if ((RR >= -1) && (RR <= 1))
				{
					float aa = ((rand() % 100) / 100.0);
					double randomPosi = abs(aa * bestPosi[k] - Popu[j][k]);
					Popu[j][k] = bestPosi[k] - r * randomPosi * cos(double(teta / 180) * pi);
				}
				else
				{
					double b = (rand() % 1000) / 1000.0;
					double cp = floor(b * popSize);
					posi candidatePosi;
					for (int s = 0; s < dim; s++)
						candidatePosi.push_back(Popu[cp][s]);
					double c = (rand() % 1000) / 1000.0;
					Popu[j][k] = r * (candidatePosi[k] - c * Popu[j][k]);
				}
			}
			 
		}
		for (int j = 0; j < popSize; j++)
		{
			bool flagUb, flagLb = 0;
			for (int k = 0; k < dim; k++)
			{
				flagUb = Popu[j][k] > ub[k];
				flagLb = Popu[j][k] < lb[k];
				Popu[j][k] = Popu[j][k] * (!(flagUb + flagLb)) + ub[k] * flagUb + lb[k] * flagLb;
			}
		}
		vector<double>Scores = calFitness(func, Popu);
		//cout << "第" << i+1 << "迭代后的位置：" << endl;
		//displayPop(Popu);
		//cout << "第" << i + 1 << "迭代后的得分：" << endl;
		for (int m = 0; m < Scores.size(); m++)
		{
			//cout << Scores[m] << endl;
			if (Scores[m] < bestScore)
			{
				bestScore = Scores[m];
				bestPosi.clear();
				for (int n = 0; n < dim; n++)
				{
					bestPosi.push_back(Popu[m][n]);
				}
			}
		}
		bestScores.push_back(bestScore);
	}
	return bestPosi;
}


int main()
{
	/*****************************test****************************************/
	/*population pop;
	for (int i = 0; i < 4; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			posi.push_back(2);
		}
		pop.push_back(posi);
		posi.clear();
	}

	for (int i = 0; i < pop.size(); i++)
	{
		for (int j = 0; j < pop[i].size(); j++)
		{
			cout << pop[i][j] << "    ";
		}
		cout << endl;
	}
	*/

	/*debug for initialize */
	double up_bound[2] = { 2,2 };
	double low_bound[2] = { -2,-2 };
	vector<double>ub(up_bound, up_bound + sizeof(up_bound));
	vector<double>lb(low_bound, low_bound + sizeof(low_bound));
	//population originP = initialize(20, 2, ub, lb);
	//displayPop(originP);
	int func = 2;
	//vector<double>origin_scores = calFitness(func, originP);
	vector<double>bestScores;
	posi finalPosi = scso(100, 2, ub, lb, 100, func, bestScores);
	
	int dim = 2;
	//输出决策变量值
	for (int i = 0; i < dim; i++)
	{
		cout << finalPosi[i] << ",     ";
	}
	cout << "最优目标函数值为：" << bestScores[bestScores.size() - 1] << endl;
	//输出算法收敛数据
	ofstream outfile;
	time_t now = time(0);
	// 把 now 转换为字符串形式
	string time = to_string(now);
	outfile.open("E:\\615所\\学习\\航路规划\\SCSO\\SCSO\\log\\" + time + "Convergence_curve.txt");
	for (int i = 0; i < bestScores.size(); i++)
	{
		outfile << bestScores[i] << endl;
	}
	outfile.close();
}


